﻿using System.IO;
using lucere.io.concurrency;

namespace lucere.io
{
	/// <summary>
	/// Base class for Directory implementations that store index
	/// files in the file system.  There are currently three core
	/// subclasses:
	/// <ul>
	/// <li> {@link SimpleFSDirectory} is a straightforward
	/// implementation using java.io.RandomAccessFile.
	/// However, it has poor concurrent performance
	/// (multiple threads will bottleneck) as it
	/// synchronizes when multiple threads read from the
	/// same file.
	/// <li> {@link NIOFSDirectory} uses java.nio's
	/// FileChannel's positional io when reading to avoid
	/// synchronization when reading from the same file.
	/// Unfortunately, due to a Windows-only <ahref="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6265734">Sun
	/// JRE bug</a> this is a poor choice for Windows, but
	/// on all other platforms this is the preferred
	/// choice.
	/// <li> {@link MMapDirectory} uses memory-mapped IO when
	/// reading. This is a good choice if you have plenty
	/// of virtual memory relative to your index size, eg
	/// if you are running on a 64 bit JRE, or you are
	/// running on a 32 bit JRE but your index sizes are
	/// small enough to fit into the virtual memory space.
	/// Java has currently the limitation of not being able to
	/// unmap files from user code. The files are unmapped, when GC
	/// releases the byte buffers. Due to
	/// <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4724038">
	/// this bug</a> in Sun's JRE, MMapDirectory's {@link IndexInput#close}
	/// is unable to close the underlying OS file handle. Only when
	/// GC finally collects the underlying objects, which could be
	/// quite some time later, will the file handle be closed.
	/// This will consume additional transient disk usage: on Windows,
	/// attempts to delete or overwrite the files will result in an
	/// exception; on other platforms, which typically have a &quot;delete on
	/// last close&quot; semantics, while such operations will succeed, the bytes
	/// are still consuming space on disk.  For many applications this
	/// limitation is not a problem (e.g. if you have plenty of disk space,
	/// and you don't rely on overwriting files on Windows) but it's still
	/// an important limitation to be aware of. This class supplies a
	/// (possibly dangerous) workaround mentioned in the bug report,
	/// which may fail on non-Sun JVMs.
	/// </ul>Unfortunately, because of system peculiarities, there is
	/// no single overall best implementation.  Therefore, we've
	/// added the {@link #open} method, to allow Lucene to choose
	/// the best FSDirectory implementation given your
	/// environment, and the known limitations of each
	/// implementation.  For users who have no reason to prefer a
	/// specific implementation, it's best to simply use {@link
	/// #open}.  For all others, you should instantiate the
	/// desired implementation directly.
	/// <p>The locking implementation is by default {@link NativeFSLockFactory}, but can be changed by
	/// passing in a custom {@link LockFactory} instance.
	/// @see Directory
	/// </summary>
	public interface IFSDirectory : IDirectory
	{
		void CreateDir();

		/// <summary>
		/// Creates an FSDirectory instance, trying to pick the
		/// best implementation given the current environment.
		/// The directory returned uses the {@link NativeFSLockFactory}.
		/// <p>Currently this returns {@link NIOFSDirectory}
		/// on non-Windows JREs and {@link SimpleFSDirectory}
		/// on Windows.
		/// <p><b>NOTE</b>: this method may suddenly change which
		/// implementation is returned from release to release, in
		/// the event that higher performance defaults become
		/// possible; if the precise implementation is important to
		/// your application, please instantiate it directly,
		/// instead. On 64 bit systems, it may also good to
		/// return {@link MMapDirectory}, but this is disabled
		/// because of officially missing unmap support in Java.
		/// For optimal performance you should consider using
		/// this implementation on 64 bit JVMs.
		/// <p>See <a href="#subclasses">above</a> /
		/// </summary>
		/// <param name="path"></param>
		/// <returns></returns>
		IFSDirectory Open(FileInfo path);

		/// <summary>
		/// Just like {@link #open(File)}, but allows you to
		/// also specify a custom {@link LockFactory}.
		/// </summary>
		/// <param name="path"></param>
		/// <param name="lockFactory"></param>
		/// <returns></returns>
		IFSDirectory Open(FileInfo path, ILockFactory lockFactory);

		/// <summary>
		/// Lists all files (not subdirectories) in the
		/// directory.  This method never returns null (throws
		/// {@link IOException} instead).
		/// @throws NoSuchDirectoryException if the directory
		/// does not exist, or does exist but is not a
		/// directory.
		/// @throws IOException if list() returns null
		/// </summary>
		/// <param name="directory"></param>
		/// <returns></returns>
		string[] ListAll(DirectoryInfo directory);

		/// <summary>
		/// Returns the time the named file was last modified.
		/// </summary>
		/// <param name="directory"></param>
		/// <param name="fileName"></param>
		/// <returns></returns>
		long FileModified(DirectoryInfo directory, string fileName);

		DirectoryInfo DirectoryInfo { get; }

		/// <summary>
		/// Sets the maximum number of bytes read at once from the
		/// underlying file during {@link IndexInput#readBytes}.
		/// The default value is {@link #DEFAULT_READ_CHUNK_SIZE};
		/// <p> This was introduced due to <a
		/// href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6478546">Sun
		/// JVM Bug 6478546</a>, which throws an incorrect
		/// OutOfMemoryError when attempting to read too many bytes
		/// at once.  It only happens on 32bit JVMs with a large
		/// maximum heap size.</p>
		/// <p>Changes to this value will not impact any
		/// already-opened {@link IndexInput}s.  You should call
		/// this before attempting to open an index on the
		/// directory.</p>
		/// <p> <b>NOTE</b>: This value should be as large as
		/// possible to reduce any possible performance impact.  If
		/// you still encounter an incorrect OutOfMemoryError,
		/// trying lowering the chunk size.</p>
		///  </summary>
		int ReadChunkSize { get; set; }

	}
}